package com.itlong.cloud.smartcard.service.impl;


import com.alibaba.fastjson.JSON;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardGetDeviceInfoDTO;
import com.itlong.cloud.POJO.DTO.smartcard.SmartCardSyncDeviceInfoDTO;
import com.itlong.cloud.POJO.PO.DeviceElevatorFloorConfigPO;
import com.itlong.cloud.POJO.PO.DeviceElevatorInfoPO;
import com.itlong.cloud.POJO.PO.DeviceEntranceInfoPO;
import com.itlong.cloud.POJO.VO.smartcard.*;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RabbitMQConstant;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.PropertyEquipTypeEnum;
import com.itlong.cloud.property.dao.IDeviceElevatorFloorConfigDao;
import com.itlong.cloud.property.dao.IDeviceEntranceInfoDao;
import com.itlong.cloud.property.dao.IPropertyElevatorDao;
import com.itlong.cloud.property.dao.IPropertyEquipDao;
import com.itlong.cloud.rabbitmq.config.MessageSender;
import com.itlong.cloud.smartcard.dao.ISmartCardDeviceDao;
import com.itlong.cloud.smartcard.service.ISmartCardDeviceInfoService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
public class SmartCardDeviceInfoServiceImpl implements ISmartCardDeviceInfoService {

    private static Logger LOG = LoggerFactory.getLogger(SmartCardDeviceInfoServiceImpl.class);

    //APP redis变更发送
    @Autowired
    MessageSender messageSender;

    @Autowired
    IDeviceEntranceInfoDao iDeviceEntranceInfoDao;//电梯楼层映射操作数据接口
    @Autowired
    IPropertyElevatorDao iPropertyElevatorDao;
    @Autowired
    IDeviceElevatorFloorConfigDao iDeviceElevatorFloorConfigDao;
    @Autowired
    IPropertyEquipDao iPropertyEquipDao;

    ////一卡通设备操作数据库接口
    @Autowired
    ISmartCardDeviceDao iSmartCardDeviceDao;

    /**
     * <desc>
     *      保存或更新电梯楼层映射信息
     * <desc/>
     *
     * @param deviceElevatorFloorConfigPO 电梯楼层映射表
     * @return
     * @author zhans
     * @createDate 2017/11/20
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void saveOrUpdatefloorConfig(DeviceElevatorFloorConfigPO deviceElevatorFloorConfigPO) throws Exception {

        this.preHandleBeforeSaveFloorConfig(deviceElevatorFloorConfigPO.getDeviceUnique());
        List<DeviceElevatorFloorConfigPO> deviceElevatorFloorConfigPOS = iDeviceElevatorFloorConfigDao.getElevatorFloorConfigByPO(deviceElevatorFloorConfigPO);
        if ((deviceElevatorFloorConfigPOS == null ||(deviceElevatorFloorConfigPOS.isEmpty()))) {
            iDeviceElevatorFloorConfigDao.save(SqlUtil.durableData(deviceElevatorFloorConfigPO, PlatformConstants.TABLE_SAVE));
        } else {
            iDeviceElevatorFloorConfigDao.update(deviceElevatorFloorConfigPO);
            //String projectId = StringHandlerUtil.copySubStr(deviceElevatorFloorConfigPO.getDeviceUnique(),0,8);
            //this.sendMessageForDeviceChanged(projectId); //转移到定时任务中，批量操作后再执行通知
        }

    }

    /**
     * <desc>
     * 一卡通更新设备信息。
     * <desc/>
     *
     * @param deviceInfoDTO 更新设备信息参数
     * @return
     * @author LouisLewis
     * @createDate 2017-12-27
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer updateDeviceInfo(SmartCardSyncDeviceInfoDTO deviceInfoDTO) throws Exception {
        Integer resCount = 0;
        switch (PropertyEquipTypeEnum.getByEquipType(deviceInfoDTO.getDeviceType())){
            case ELEVATOR:
                DeviceElevatorInfoPO elevatorInfoPO = new DeviceElevatorInfoPO();
                elevatorInfoPO.setDeviceUnique(deviceInfoDTO.getDeviceUnique());
                elevatorInfoPO.setDeviceName(deviceInfoDTO.getDeviceName());
                elevatorInfoPO.setProjectId(deviceInfoDTO.getProjectId());
                if(StringUtils.isNotEmpty(deviceInfoDTO.getDeviceMemo())){
                    elevatorInfoPO.setDeviceMemo(deviceInfoDTO.getDeviceMemo());
                }
                elevatorInfoPO.setUpdateTime(new Date());
                //保存电梯设备信息
                resCount = iSmartCardDeviceDao.updateElevatorDevice(SqlUtil.durableData(elevatorInfoPO, PlatformConstants.TABLE_UPDATE));
                this.preHandleBeforeSaveFloorConfig(deviceInfoDTO.getDeviceUnique());
                break;
            case ENTRANCE:
                DeviceEntranceInfoPO entranceInfoPO = new DeviceEntranceInfoPO(
                        deviceInfoDTO.getDeviceUnique(),
                        deviceInfoDTO.getDeviceId(),
                        deviceInfoDTO.getDeviceName(),
                        deviceInfoDTO.getProjectId()
                );
                entranceInfoPO.setUpdateTime(new Date());
                if(StringUtils.isNotEmpty(deviceInfoDTO.getDeviceMemo())){
                    entranceInfoPO.setDeviceMemo(deviceInfoDTO.getDeviceMemo());
                }
                resCount = iSmartCardDeviceDao.updateEntranceDevice(SqlUtil.durableData(entranceInfoPO, PlatformConstants.TABLE_UPDATE));
                break;
            default:
                LOG.info(String.format("无法更新不支持的一卡通设备类型:%s",deviceInfoDTO));
                break;
        }
        //this.sendMessageForDeviceChanged(deviceInfoDTO.getProjectId()); 转移到定时任务中，批量操作后再执行通知
        return resCount;
    }

    /**
     * <desc>
     * 一卡通_添加设备。
     * <desc/>
     *
     * @param deviceInfoDTO 设备信息
     * @return
     * @author LouisLewis
     * @createDate 2017-12-27
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public Integer addDeviceInfo(SmartCardSyncDeviceInfoDTO deviceInfoDTO) throws Exception {
        Integer resCount = 0;
        Date date = new Date();
        switch (PropertyEquipTypeEnum.getByEquipType(deviceInfoDTO.getDeviceType())) {
            case ELEVATOR:
                DeviceElevatorInfoPO elevatorInfoPO = new DeviceElevatorInfoPO(
                        deviceInfoDTO.getDeviceUnique(),
                        deviceInfoDTO.getDeviceName(),
                        deviceInfoDTO.getProjectId(),
                        null,  //起始楼层
                        null, //结束楼层数
                        deviceInfoDTO.getDeviceId()
                );
                elevatorInfoPO.setDeviceMemo(deviceInfoDTO.getDeviceMemo());

                elevatorInfoPO.setCreateTime(date);
                elevatorInfoPO.setUpdateTime(date);
                elevatorInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
                resCount = iSmartCardDeviceDao.addElevatorDevice(SqlUtil.durableData(elevatorInfoPO, PlatformConstants.TABLE_SAVE));
                this.preHandleBeforeSaveFloorConfig(deviceInfoDTO.getDeviceUnique());
                break;
            case ENTRANCE:
                DeviceEntranceInfoPO entranceInfoPO = new DeviceEntranceInfoPO(
                        deviceInfoDTO.getDeviceUnique(),
                        deviceInfoDTO.getDeviceId(),
                        deviceInfoDTO.getDeviceName(),
                        deviceInfoDTO.getProjectId()
                );
                entranceInfoPO.setDeviceMemo(deviceInfoDTO.getDeviceMemo());
                entranceInfoPO.setCreateTime(date);
                entranceInfoPO.setUpdateTime(date);
                entranceInfoPO.setStatus(DataStatusEnum.NORMAL.getType());
                resCount = iSmartCardDeviceDao.addEntranceDevice(SqlUtil.durableData(entranceInfoPO, PlatformConstants.TABLE_SAVE));
                break;
            default:
                break;
        }

        return resCount;
    }

    /**
     * <desc>
     * 查询一卡通通行记录相关的设备信息.
     * </desc>
     *
     * @param getDeviceInfoDTO 查询条件
     * @return 设备信息
     * @author LewisLouis
     * @createDate 2018-01-23
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.NOT_SUPPORTED)
    public List<SmartCardDeviceInfoVO> getDeviceInfos(SmartCardGetDeviceInfoDTO getDeviceInfoDTO) throws Exception {
        return iSmartCardDeviceDao.getDeviceInfos(getDeviceInfoDTO);
    }

    /**
     * <desc>
     *     在保存同步的楼层对应表前进行数据检查，若上不存在，则需初始化1-112层的数据
     * </desc>
     *
     * @param  deviceUnique 设备唯一Id
     * @return 无
     * @author LewisLouis
     * @createDate 2017-12-26
     */
    private void preHandleBeforeSaveFloorConfig(String deviceUnique){

        List<DeviceElevatorFloorConfigPO> floorConfigPOS = iDeviceElevatorFloorConfigDao.getFloorConfigIdList(deviceUnique);
        //若有112数据无需处理
        if ((floorConfigPOS != null) && (floorConfigPOS.size() == PlatformConstants.MAX_ELEVATOR_FLOORNUM)){
            return;
        }

        //清理不足112层的脏数据
        if ((floorConfigPOS != null) && (floorConfigPOS.size() < PlatformConstants.MAX_ELEVATOR_FLOORNUM)){
            iDeviceElevatorFloorConfigDao.delByDeviceUnique(deviceUnique);
        }
        Integer naturalFloor = 1;
        List<DeviceElevatorFloorConfigPO> floorConfigPOList = new ArrayList<>();
        for (int floorIndex = 1; floorIndex <= PlatformConstants.MAX_ELEVATOR_FLOORNUM; floorIndex++) {
            DeviceElevatorFloorConfigPO floorConfigPO = new DeviceElevatorFloorConfigPO("", deviceUnique, (naturalFloor++).toString());
            floorConfigPO.setStatus(DataStatusEnum.NORMAL.getType());
            Date date = new Date();
            floorConfigPO.setLogicalFloor(String.format("%d层",floorIndex));
            floorConfigPO.setFloorNum(floorIndex);
            floorConfigPO.setDetectFloor(floorIndex+"");
            floorConfigPO.setTerminalFloor(floorIndex+"");
            floorConfigPO.setCreateTime(date);
            floorConfigPO.setUpdateTime(date);
            floorConfigPOList.add(floorConfigPO);
        }
        if (!floorConfigPOList.isEmpty()) {
            iDeviceElevatorFloorConfigDao.saveBatch(floorConfigPOList);
        }
    }

     /**
     * <desc>
     *      设备变更或电梯楼层对应表变更，按项目需通知更新APP_USR的缓存. （慎用！！！）
     * </desc>
     *
     * @param  projectId 项目Id
     * @return xx
     * @author LewisLouis
     * @createDate 2017-12-29
     */
     @Override
    public void sendMessageForDeviceChanged(String projectId) throws Exception {
        if (StringUtils.isBlank(projectId)){
            LOG.info("消息通知一卡通_APP用户设备信息变更失败：projectId 为空");
            return;
        }
        //住户设备权限更新时通知后台移动App模块
        Map<String, Object> param = new HashMap<>();
       // param.put("userId", userId);
        param.put("projectId", projectId);
        messageSender.send(RabbitMQConstant.RABBITMQ_EQUIP_APP_USER_INFO_DEVICE_UPDATE_QUEUE,
                JSON.toJSONString(param), RabbitMQConstant.RABBITMQ_EQUIP_EXCHANGE,
                RabbitMQConstant.RABBITMQ_EQUIP_APP_USER_INFO_DEVICE_UPDATE_KEY);

        //LOG.info(String.format("消息通知一卡通_APP用户设备信息变更：projectId-%s", projectId));
    }

    /**
     * <desc>
     *      根据项目编号获取云电梯信息
     * </desc>
     *
     * @param  projectId 项目Id
     * @return 云电梯信息
     * @author Qiang.S
     * @createDate 2019-01-26
     */
    @Override
    public List<SmartCardOldDeviceInfoVO> getCloudElevatorList(String projectId) throws Exception {
        return iPropertyElevatorDao.getCloudElevatorList(projectId);
    }

    /**
     * <desc>
     *     获取云电梯楼层映射表信息
     * <desc/>
     *
     * @param deviceUnique 设备唯一编号
     * @return
     * @author Qiang.S
     * @createDate 2019-01-26
     */
    @Override
    public SmartCardFloorInfoVO getElevatorFloorConfig(String deviceUnique) throws Exception {
        return iPropertyElevatorDao.getElevatorFloorConfig(deviceUnique);
    }

    /**
     * <desc>
     *      一卡通获取楼层映射表
     * </desc>
     *
     * @param deviceUnique
     * @return
     * @author Jiaqi.X
     * @createDate 2019/03/29
     */
    public List<SmartCardServerFloorRelationVO> getSmartCardServerFloorRelation(String deviceUnique){
        List<SmartCardServerFloorRelationVO> list = iPropertyElevatorDao.getSmartCardServerFloorRelation(deviceUnique);
        //查询需要同步的楼层映射表序列号
        String projectId = StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique);
        String tableName = "smartcard_pull_cloud_"+projectId;
        //更新云端的同步序列号
        iPropertyElevatorDao.setFloorRelationSyncSerialNo(tableName,deviceUnique);
        return list;
    }

    /**
     * <desc>
     *      检测设备是否存在
     * </desc>
     *
     * @param deviceUnique
     * @return
     * @authro Jiaqi.X
     * @createDate 2019/11/11
     */
    public Integer checkDeviceIsOnline(String deviceUnique){
        Integer result = 0;
        if(StringUtils.isNotBlank(deviceUnique)) {
            Integer type = StringHandlerUtil.getDeviceTypeByDeviceUnique(deviceUnique);
            if (type == 1) {
                //电梯
                result = iPropertyElevatorDao.checkSmartCardElevatorIsOnline(deviceUnique);
            } else if (type == 2) {
                //门禁
                result = iDeviceEntranceInfoDao.checkSmartCardEntranceIsOnline(deviceUnique);
            }
        }
        return result;
    }

    /**
     * <desc>
     *      获取所有设备
     * </desc>
     *
     * @param projectId
     * @return
     * @createDate 2019/11/25
     * @author Jiaqi.X
     */
    public Map<String,Object> getAllDevice(String projectId){
        Map<String,Object> result = new HashMap<>();
        result.put("elevators",iPropertyEquipDao.getAllDevice(projectId,1));
        result.put("entrances",iPropertyEquipDao.getAllDevice(projectId,2));
        return result;
    }
}
